<?php
namespace app\beautiful\controller\miniapp\member;
use app\BaseController;
use app\beautiful\logic\printer\PrinterLogic;
use app\beautiful\model\appointment\AppointmentModel;
use app\beautiful\model\appointment\AppointmentSettingModel;
use app\beautiful\model\appointment\TechnicianModel;
use app\beautiful\model\appointment\TechnicianProjectModel;
use app\beautiful\model\appointment\TechnicianSchedulingModel;
use app\beautiful\model\member\MemberProjectModel;
use app\beautiful\model\project\ProjectModel;
use app\beautiful\model\project\ProjectTypeModel;
use app\beautiful\model\setting\SettingSmsModel;
use app\common\logic\SmsLogic;
use app\common\model\ShopStoreModel;

class Appointment extends BaseController{

    protected $setting;
    protected function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
        if(null === $setting= AppointmentSettingModel::where([['shop_id','=',$this->request->shopId]])->find()){
            $this->error('您还未设置预约')->send();
            die();
        }
        $this->setting=$setting;

        if(!in_array(date('w',$this->request->time()),$this->setting->week)){
            $this->error($this->setting->rest_notice)->send();
            die();
        }

    }

    public function showAppointment()
    {
        $technician_data=$this->getTechnicianData();
        $project_type_data=$this->getProjectTypeData();
        $project_data=$this->getProjectData();

        $return=[
            'technician_data'=>$technician_data,
            'project_type_data'=>$project_type_data,
            'project_data'=>$project_data,
        ];
        return $this->success($return);
    }

    public function getTechnicianDetail()
    {
        $technician_id=$this->request->param('technician_id/d',0);
        if($technician_id==0) return $this->error('技师不存在');
        if(null === $technician = TechnicianModel::find($technician_id)) return $this->error('技师不存在');
        if($technician->shop_id != $this->request->shopId) return $this->error('技师不存在');
        if($technician->is_delete != 0) return $this->error('技师不存在');
        $engaged_num=TechnicianProjectModel::where([
            ['shop_id','=',$this->request->shopId],
            ['technician_id','=',$technician_id],
            ['is_delete','=',0]
        ])->sum('engaged_num') ?? 0;

        $project_data=TechnicianProjectModel::with(['project'=>function($query){
            $query->where([['is_delete','=',0]])
                ->field('project_id,abbreviation,market_price,cover_img');
        }])->where([
                ['shop_id','=',$this->request->shopId],
                ['technician_id','=',$technician_id],
                ['is_delete','=',0]
            ])->order(['engaged_num'=>'desc'])
            ->field('project_id,engaged_num')
            ->select()
            ->toArray();
        foreach ($project_data as $k => $v){
            if(!$v['project']){
                unset($project_data[$k]);
            }
        }

        $detail=[
            'face'=>$technician->face,
            'name'=>$technician->name,
            'working_collar'=>$technician->working_collar,
            'position'=>$technician->position,
            'engaged_num'=>$engaged_num,
            'brief_introduction'=>$technician->brief_introduction,
            'tags'=>$technician->tags ?? [],
            'project_data'=>$project_data,
        ];

        return $this->success(['detail'=>$detail]);
    }

    public function showAppointmentApply()
    {
        $project_id = $this->request->param('project_id/d',0);

        if(null === $project = ProjectModel::find($project_id)) return $this->error('服务项目不存在');
        if($project->shop_id != $this->request->shopId) return $this->error('服务项目不存在');
        if($project->is_delete != 0) return $this->error('服务项目不存在');
        $engaged_num=TechnicianProjectModel::where([
            ['shop_id','=',$this->request->shopId],
            ['project_id','=',$project_id]
        ])->sum('engaged_num') ?? 0;

        $project_detail=[
            'project_id'=>$project->project_id,
            'abbreviation'=>$project->abbreviation,
            'market_price'=>$project->market_price,
            'cover_img'=>$project->cover_img,
            'engaged_num'=>$engaged_num,
        ];

        $technician_ids=TechnicianProjectModel::where([
                ['shop_id','=',$this->request->shopId],
                ['project_id','=',$project_id],
                ['is_delete','=',0]
            ])->column('technician_id') ?? [];

        $technician_data=$this->getTechnicianData($technician_ids);

        $return=[
            'project_detail'=>$project_detail,
            'technician_data'=>$technician_data,
            'week'=>$this->setting->week,
        ];
        return $this->success($return);
    }

    public function getAppointmentApplyTime()
    {
        $today=date("Y-m-d",$this->request->time());
        $project_id = $this->request->param('project_id/d',0);

        $day=$this->request->param('day');
        if(empty($day)) return $this->error('请选择预约日期');
        if(false === $day_unix=strtotime($day.' 00.00.00')) return $this->error('请选择预约日期');
        if(!in_array(date('w',$day_unix),$this->setting->week)) return $this->error('选的日期不能进行预约');
        if($day<$today) return $this->error('预约日期不能低于今天');

        if(null === $project = ProjectModel::find($project_id)) return $this->error('服务项目不存在');
        if($project->shop_id != $this->request->shopId) return $this->error('服务项目不存在');
        if($project->is_delete != 0) return $this->error('服务项目不存在');

        $technician_id=$this->request->param('technician_id/d',0);
        if($technician_id != 0){
            if(null === $technician = TechnicianModel::find($technician_id)) return $this->error('技师不存在');
            if($technician->shop_id != $this->request->shopId) return $this->error('技师不存在');
            if($technician->is_delete != 0) return $this->error('技师不存在');

            $time_list=$this->getTechnicianAppointmentTime($day,$project_id,$technician_id);
        }else{
            $time_list=$this->getAppointmentTime($day);
        }

        return $this->success(['time_list'=>$time_list]);

    }

    public function saveAppointment()
    {
        $today=date("Y-m-d",$this->request->time());
        $project_id = $this->request->param('project_id/d',0);
        $technician_id=$this->request->param('technician_id/d',0);
        $scheduling_id=$this->request->param('scheduling_id/d',0);
        $start_time=$this->request->param('start_time');
        $end_time=$this->request->param('end_time');
        $store_id=$this->request->param('store_id');
        //判断传来的参数
        $day=$this->request->param('day');
        if(empty($day)) return $this->error('请选择预约日期');
        if(false === $day_unix=strtotime($day.' 00.00.00')) return $this->error('请选择预约日期');
        if(!in_array(date('w',$day_unix),$this->setting->week)) return $this->error('选的日期不能进行预约');
        if($day<$today) return $this->error('预约日期不能低于今天');
        if(false === $start_time_unix=strtotime($day.' '.$start_time.':00')) return $this->error('请选择预约开始时间');
        if($start_time_unix<=$this->request->time()) return $this->error('预约开始时间低于当前时间');
        if(false === $end_time_unix=strtotime($day.' '.$end_time.':00')) return $this->error('请选择预约结束时间');
        $interval=$end_time_unix-$start_time_unix;
        if($interval<=0) return $this->error('预约开始时间不能大于结束时间');
        if($interval%1800!=0)return $this->error('预约时间间隔必须是30分钟的整倍');
        if($day.' '.$start_time<date("Y-m-d H:i",($this->request->time()+(3600*$this->setting->appointment_advance)))) return $this->error('预约时间已过');

        //判断项目
        if(null === $project = ProjectModel::find($project_id)) return $this->error('服务项目不存在');
        if($project->shop_id != $this->request->shopId) return $this->error('服务项目不存在');
        if($project->is_delete != 0) return $this->error('服务项目不存在');

        //判断是否拥有项目
        if($this->setting->check_member_project==1){
            if(null === MemberProjectModel::where([
                    ['shop_id','=',$this->request->shopId],
                    ['member_id','=',$this->request->memberId],
                    ['project_id','=',$project_id],
                    ['remain_num','>',0],
                    ['valid_end_time','>=',date("Y-m-d",$this->request->time())]
                ])->find()){
                return $this->error('您没有这个项目,无法预约');
            }
        }

        //判断一个项目只有预约一次
        if(null !== AppointmentModel::where([
                ['shop_id','=',$this->request->shopId],
                ['status','in',[1,4,8]],
                ['day','=',$day],
                ['member_id','=',$this->request->memberId]
            ])->find()){
            return $this->error('这个项目您今天已经预约过了');
        }

        if($technician_id != 0){
            //有技师的情况
            //判断技师
            if(null === $technician = TechnicianModel::find($technician_id)) return $this->error('技师不存在');
            if($technician->shop_id != $this->request->shopId) return $this->error('技师不存在');
            if($technician->is_delete != 0) return $this->error('技师不存在');

            //判断技师的排班
            if($scheduling_id==0) return $this->error('请选择时间');
            if(null === $scheduling = TechnicianSchedulingModel::find($scheduling_id)) return $this->error('请选择时间');
            if($scheduling->shop_id != $this->request->shopId) return $this->error('请选择时间');
            if($scheduling->is_delete != 0) return $this->error('请选择时间');
            if($scheduling->technician_id != $technician_id) return $this->error('请选择时间');
            if($scheduling->day != $day) return $this->error('请选择时间');
            if($scheduling->project_id != $project_id) return $this->error('请选择时间');

            //判断技师排班的数量有没有超过
            $scheduling_num=AppointmentModel::where([
                ['shop_id','=',$this->request->shopId],
                ['scheduling_id','=',$scheduling_id],
                ['status','in',[1,4,8]]
            ])->count() ?? 0;

            $appointment_num=$scheduling->appointment_num ==0 ? $this->setting->appointment_num : $scheduling->appointment_num;
            if($scheduling_num>=$appointment_num) return $this->error('该时间段预约已经满了，请重新选择');
        }else{
            //没有技师的情况
            //判断时间段的预约数
            $appointment_num = AppointmentModel::where([
                ['shop_id','=',$this->request->shopId],
                ['status','in',[1,4,8]],
                ['day','=',$day],
            ])->whereRaw("(start_time <= '{$start_time}' and end_time >= '{$start_time}') or (start_time <= '{$end_time}' and end_time >= '{$end_time}')")
                ->count() ?? 0;

            if($appointment_num>=$this->setting->appointment_num) return $this->error('该时间段预约已经满了，请重新选择');
        }

        $appointment_model=new AppointmentModel();
        $appointment_model->shop_id=$this->request->shopId;
        $appointment_model->member_id=$this->request->memberId;
        $appointment_model->member_name=$this->request->member->nick_name;
        $appointment_model->member_mobile=$this->request->member->mobile;
        $appointment_model->project_id=$project_id;
        $appointment_model->project_name=$project->abbreviation;
        $appointment_model->project_cover_img=$project->cover_img;
        $appointment_model->technician_id=$technician_id;
        if($technician_id!=0){
            $appointment_model->scheduling_id=$scheduling_id;
            $appointment_model->technician_name=$technician->name;
            $appointment_model->technician_mobile=$technician->mobile;
        }

        $appointment_model->day=$day;
        $appointment_model->start_time=$start_time;
        $appointment_model->end_time=$end_time;
        $appointment_model->store_id=$store_id;
        $appointment_model->save();

        try{
            //发送短信给用户
            $sms_setting = SettingSmsModel::where([['shop_id','=',$this->request->shopId]])->find();
            if(null !== $sms_setting){
                if($sms_setting->appointment_notice_member==1){
                    $sms_logic= new SmsLogic();
                    $params=[
                        'xm'=>$project->abbreviation,
                        't'=>$start_time.'-'.$end_time
                    ];
                    $sms_logic->send($this->request->shopId,[$this->request->member->mobile],$params,'appointmentNoticeMember');
                }

                //发送短信给服务人员
                if($technician_id !=0 ){
                    if($sms_setting->appointment_notice_service_person==1){
                        $sms_logic= new SmsLogic();
                        $params=[
                            'mobile'=>$this->request->member->mobile,
                            'xm'=>$project->abbreviation,
                            't'=>$start_time.'-'.$end_time
                        ];
                        $sms_logic->send($this->request->shopId,[$technician->mobile],$params,'appointmentNoticeServicePerson');
                    }
                }

                //发送给管理员
                if($sms_setting->appointment_notice_admin==1 && !empty($sms_setting->boss_mobiles)){
                    $sms_logic= new SmsLogic();
                    $params=[
                        'mobile'=>$this->request->member->mobile,
                        'xm'=>$project->abbreviation,
                        't'=>$start_time.'-'.$end_time
                    ];
                    $sms_logic->send($this->request->shopId,$sms_setting->boss_mobiles,$params,'appointmentNoticeAdmin');
                }
            }


        }catch (\Exception $e){

        }

        //打印机
        $printer_logic =new PrinterLogic($this->request->shopId);
        $printer_logic->print('appointment',$appointment_model->appointment_id);
        return $this->success('操作成功');
    }

    public function getMemberAppoinment()
    {
        $type=$this->request->param('type/d',0);
        $where=[
            ['shop_id','=',$this->request->shopId],
            ['member_id','=',$this->request->memberId],
        ];
        switch ($type){
            case 1:
                $where[]=['status','=',4];
                break;
            case 2:
                $where[]=['status','=',8];
                break;
            case 3:
                $where[]=['status','=',-1];
                break;
            default:
                $where[]=['status','=',1];
                break;
        }

        $order=['add_time'=>'desc'];
        $field="appointment_id,project_name,project_cover_img,technician_id,day,start_time,end_time,status,reason,cancel_time,operate_type,operate_name";
        $append=['appointment_time_format','cancel_time_small_format'];

        $appointment_model = new AppointmentModel();
        $datas=$appointment_model->with(['technician'=>function($query){
            $query->field('technician_id,name,face,mobile');
        }])->where($where)
            ->order($order)
            ->field($field)
            ->limit($this->request->limit)
            ->page($this->request->page)
            ->select()
            ->append($append)
            ->toArray();
        return $this->success(['datas'=>$datas]);
    }

    public function cancelAppointment()
    {
        $appointment_id=$this->request->param('appointment_id/d',0);
        $reason=$this->request->param('reason');

        if($appointment_id==0) return $this->error('预约不存在');

        if(null == $appointment = AppointmentModel::find($appointment_id)) return $this->error('预约不存在');
        if($appointment->shop_id != $this->request->shopId) return $this->error('预约不存在');
        if(!in_array($appointment->status,[1,4])) return $this->error('预约不存在');
        if($appointment->member_id != $this->request->memberId) return $this->error('预约不存在');

        $appointment->status=-1;
        $appointment->cancel_time=$this->request->time();
        $appointment->reason=$reason;
        $appointment->operate_type=0;
        $appointment->save();
        return $this->success('取消预约成功');
    }

    protected function getTechnicianAppointmentTime($day,$project_id,$technician_id)
    {
        $schedulings=TechnicianSchedulingModel::withCount(['appointment'=>function($query){
            $query->where([
                ['shop_id','=',$this->request->shopId],
                ['status','in',[1,4,8]]
            ]);
        }])->where([
            ['shop_id','=',$this->request->shopId],
            ['technician_id','=',$technician_id],
            ['project_id','=',$project_id],
            ['day','=',$day],
            ['is_delete','=',0],
        ])->field('scheduling_id,start_time,end_time')
            ->select()
            ->toArray();
        foreach ($schedulings  as $k => $v){
            if($day.' '.$v['start_time']<date("Y-m-d H:i",($this->request->time()+(3600*$this->setting->appointment_advance)))){
                $schedulings[$k]['status']=0;
            }else{
                $appointment_num=$v['appointment_num'] ==0 ? $this->setting->appointment_num : $v['appointment_num'];
                if($v['appointment_count'] >= $appointment_num){
                    $schedulings[$k]['status']=0;
                }else{
                    $schedulings[$k]['status']=1;
                }
            }
        }
        return $schedulings;

    }

    public function getAppointmentTime($day)
    {
        $today=date("Y-m-d",$this->request->time());
        $start_time=$this->setting->start_time; $end_time=$this->setting->end_time;
        $appointment_interval=$this->setting->appointment_interval;
        $appointment_advance=$this->setting->appointment_advance;
        $appointment_num=$this->setting->appointment_num;

        $start_time_mintures=$this->ChangeStrToMinutes($start_time);
        $end_time_mintures=$this->ChangeStrToMinutes($end_time);

        $length=(int)ceil(($end_time_mintures-$start_time_mintures)/$appointment_interval);

        $appointment_data=AppointmentModel::where([
            ['shop_id','=',$this->request->shopId],
            ['status','in',[1,4,8]],
            ['day','=',$day],
        ])->field('start_time,end_time')->select()->toArray();

        $datas=[];
        for ($k=0;$k<$length;$k++){
            $datas[$k]['start_time']=$this->ChangeHourMinutestr($start_time_mintures+($appointment_interval)*$k);
            if($k==$length-1){
                $datas[$k]['end_time']=$end_time;
            }else{
                $datas[$k]['end_time']=$this->ChangeHourMinutestr($start_time_mintures+($appointment_interval)*($k+1));
            }

            if($day.' '.$datas[$k]['start_time']<date("Y-m-d H:i",($this->request->time()+(3600*$appointment_advance)))){
                $datas[$k]['status']=0;
            }else{
                $num=0;
                foreach ($appointment_data as $key => $val){
                    if(($val['start_time']>=$datas[$k]['start_time'] && $val['start_time']<$datas[$k]['end_time']) ||
                        ($val['end_time']>$datas[$k]['start_time'] && $val['end_time']<=$datas[$k]['end_time'])){
                        $num++;
                    }
                }

                if($num>=$appointment_num){
                    $datas[$k]['status']=0;
                }else{
                    $datas[$k]['status']=1;
                }
            }
        }

        return $datas;

    }

    public function ChangeStrToMinutes($str)
    {
        $arrminutes = explode(":",$str);
        if (count($arrminutes) == 2) {
            $minutes = $arrminutes[0] * 60 + $arrminutes[1];
            return $minutes;
        } else {
            return 0;
        }
    }

    public function ChangeHourMinutestr($str)
    {
        if ($str !== "0" && $str !== "" && $str !== null) {
            $hour=floor($str/60 ?? 0)<10 ? "0".floor($str/60 ?? 0) :floor($str/60 ?? 0);
            $minutes=($str%60 ?? 0)<10 ? "0".($str%60 ?? 0) : ($str%60 ?? 0) ;

            $hour=$hour ?? '00';
            $minutes=$minutes ?? '00';
            return $hour.":".$minutes;

//            return (strlen((string)floor($str / 60))) < 2 ? "0".(string)floor($str / 60) :
//                (string)floor($str / 60).":".(strlen((string)($str % 60))< 2 ? "0".(string)($str % 60) : (string)($str % 60));
        } else {
            return "";
        }
    }

    protected function getProjectTypeData()
    {
        $where=[
            ['shop_id','=',$this->request->shopId],
            ['is_delete','=',0]
        ];
        $datas=ProjectTypeModel::where($where)
            ->order(['sort'=>'desc'])
            ->field('project_type_id,name')
            ->select()
            ->toArray();
        array_unshift($datas,['project_type_id'=>0,'name'=>'全部']);
        return $datas;
    }

    protected function getProjectData()
    {
        $store_id = $this->request->param('store_id/d',0);
        if($store_id == 0) { 
            $where = [
                ['shop_id','=',$this->request->shopId],
                ['is_delete','=',0],
                ['enable','=',1],
                ['is_main','=',1]
            ];
            $store_id = ShopStoreModel::where($where)->value('id');
        }
        $where=[
            ['shop_id','=',$this->request->shopId],
            ['is_delete','=',0]
        ];
        $datas=ProjectModel::where($where)
            ->order(['take_count'=>'desc','market_price'=>'desc'])
            ->field('project_id,project_type_id,abbreviation,market_price,cover_img,store')
            ->select()
            ->toArray();
         // 当前服务是否属于当前门店
        if(!empty($datas)) {
            foreach($datas as $key => $value) {
                if(empty($value['store'])) {
                    unset($datas[$key]);
                }
                $store = explode(',',$value['store']);
                if(!in_array($store_id,$store)) {
                    unset($datas[$key]);
                }
            }
            $datas = array_values($datas);
        }
        if(!empty($datas)){
            $projectIds = $engaged_nums  = [];
            foreach($datas as $val){
                $projectIds[$val['project_id']] = $val['project_id'];
            }
            if(!empty($projectIds)){
                $technicianProjectModel = new TechnicianProjectModel();
                $engaged_nums =  $technicianProjectModel->getEngagedNumSumByProjectId($projectIds);
            }
            foreach ($datas as $k => $data){
                $datas[$k]['engaged_num']=$engaged_nums[$data['project_id']] ?? 0;
            }
        }

        return $datas;
    }

    protected function getTechnicianData($technician_ids=[])
    {
        $store_id = $this->request->param('store_id/d',0);
        if($store_id == 0) { 
            $where = [
                ['shop_id','=',$this->request->shopId],
                ['is_delete','=',0],
                ['enable','=',1],
                ['is_main','=',1]
            ];
            $store_id = ShopStoreModel::where($where)->value('id');
        }
        $where=[
            ['shop_id','=',$this->request->shopId],
            ['status','=',1],
            ['is_delete','=',0]
        ];

        if(!empty($technician_ids)){
            $where[]=['technician_id','in',$technician_ids];
        }

        $datas=TechnicianModel::where($where)
            ->order(['add_time'=>'desc'])
            ->field('technician_id,name,face,mobile,position,working_collar,store')
            ->select()
            ->toArray();
        // 当前教练是否属于当前门店
        if(!empty($datas)) {
            foreach($datas as $key => $value) {
                if(empty($value['store'])) {
                    unset($datas[$key]);
                }
                $store = explode(',',$value['store']);
                if(!in_array($store_id,$store)) {
                    unset($datas[$key]);
                }
            }
            $datas = array_values($datas);
        }
        if(!empty($datas)){
            $technicianIds = $engaged_nums  = [];
            foreach($datas as $val){
                $technicianIds[$val['technician_id']] = $val['technician_id'];
            }
            if(!empty($technicianIds)){
                $technicianProjectModel = new TechnicianProjectModel();
                $engaged_nums =  $technicianProjectModel->getEngagedNumSumByTechnicianId($technicianIds);
            }
            foreach ($datas as $k => $data){
                $datas[$k]['engaged_num']=$engaged_nums[$data['technician_id']] ?? 0;
            }
        }

        return $datas;
    }
    
    public function getProjectDetail() {
        $project_id = $this->request->param('project_id/d',0);
        if($project_id==0) return $this->error('项目不存在');
        $project_details = ProjectModel::where('project_id',$project_id)->value('project_details');
        return $this->success(['detail'=>json_decode($project_details,true)]);
    }
}
